Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(readr)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.3 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.2 ── Conflicts ────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(ggplot2)
library(highcharter)
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Highcharts (www.highcharts.com) is a Highsoft software product which is
not free for commercial and Governmental use
Attaching package: ‘magrittr’
The following object is masked from ‘package:purrr’:
set_names
The following object is masked from ‘package:tidyr’:
extract
EDA
Data loading
data <- read_csv("https://raw.githubusercontent.com/Alexburk93/Data_Wrangling_EDA/main/data/suicide_analysis.csv")
New names:Rows: 894 Columns: 22── Column specification ────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (13): Country name, Code, Indicator Name, Indicator Code, VAR, Variable, MEA, Measure, ISIC4...17, ISIC4...18, U...
dbl (9): Year, Age-standardized suicide rate - Sex: both sexes, Life Ladder, Social support, Healthy life expectanc...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Renaming variables and drop unwanted columns
# renaming the columns
data <- data %>%
rename(`Country_name` = `Country name`,
`Suicide_Rate` = `Age-standardized suicide rate - Sex: both sexes`,
`Life_ladder` = `Life Ladder`,
`Social_support` = `Social support`,
`Life_expectancy` = `Healthy life expectancy at birth`,
`Freedom_choices` = `Freedom to make life choices`,
`Corruption` = `Perceptions of corruption`,
`Indicator_name` = `Indicator Name`,
`Indicator_code` = `Indicator Code`)
# drop columns
# remove the original 'Time' column
data <- select(data, -Variable, -ISIC4...17, -ISIC4...18, -VAR, -MEA, -`Unit Code`)
data
Data exploration
# change names
names(data) <- make.names(names(data))
# dimensions of the dataframe
nrow(data)
[1] 894
[1] 16
[1] 894 16
# check the structure of the object
str(data)
tibble [894 × 16] (S3: tbl_df/tbl/data.frame)
$ Country_name : chr [1:894] "Australia" "Australia" "Australia" "Australia" ...
$ Code : chr [1:894] "AUS" "AUS" "AUS" "AUS" ...
$ Year : num [1:894] 2011 2011 2011 2011 2011 ...
$ Suicide_Rate : num [1:894] 10.1 10.1 10.1 10.1 11 ...
$ Life_ladder : num [1:894] 7.41 7.41 7.41 7.41 7.19 ...
$ Social_support : num [1:894] 0.967 0.967 0.967 0.967 0.954 ...
$ Life_expectancy: num [1:894] 72.3 72.3 72.3 72.3 72.1 ...
$ Freedom_choices: num [1:894] 0.945 0.945 0.945 0.945 0.935 ...
$ Corruption : num [1:894] 0.382 0.382 0.382 0.382 0.269 ...
$ Indicator_name : chr [1:894] "GDP (current US$)" "GDP (current US$)" "GDP (current US$)" "GDP (current US$)" ...
$ Indicator_code : chr [1:894] "NY.GDP.MKTP.CD" "NY.GDP.MKTP.CD" "NY.GDP.MKTP.CD" "NY.GDP.MKTP.CD" ...
$ GDP : num [1:894] 1.40e+12 1.40e+12 1.40e+12 1.40e+12 1.68e+11 ...
$ Measure : chr [1:894] "Index 2007=100" "Index 2007=100" "Index 2007=100" "Index 2007=100" ...
$ Unit : chr [1:894] "Index" "Index" "Index" "Index" ...
$ Value : num [1:894] 132 138 143 145 122 ...
$ Quarter : chr [1:894] "Q1" "Q2" "Q3" "Q4" ...
# look at columns 6, 7 and 10
head(data[ , c(2, 4:6, 12, 15)])
# look at columns 6, 7 and 10
tail(data[ , c(1, 3, 9)])
2011 2012 2013 2014 2015 2016 2017 2018 2019
100 100 100 100 100 100 100 97 97
data %>%
select(Country_name) %>%
unique() %>%
nrow()
[1] 19
unique(data$Country_name)
[1] "Australia" "New Zealand" "United States" "Spain" "Netherlands" "France"
[7] "Finland" "Belgium" "Japan" "South Africa" "Iceland" "Norway"
[13] "Sweden" "Italy" "Brazil" "United Kingdom" "Germany" "Canada"
[19] "Denmark"
[1] 2011 2012 2013 2014 2015 2016 2017 2018 2019
Interactive maps
# Set highcharter options for tooltip decimals
options(highcharter.tooltip.valueDecimals = 2)
# Create highcharter map visualization
hc <- highchart() %>%
hc_add_series_map(
worldgeojson, data, value = "GDP",
joinBy = c('name', 'Country_name'),
name = "GDP (current US$)"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "GDP in current US$")
hc
# Set highcharter options for tooltip decimals
options(highcharter.tooltip.valueDecimals = 2)
# Create map visualizations for each variable
hc_life_expectancy <- highchart() %>%
hc_add_series_map(
worldgeojson, data,
value = "Life_expectancy",
joinBy = c('name', 'Country_name'),
name = "Life Expectancy"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "Life Expectancy")
hc_suicide_rates <- highchart() %>%
hc_add_series_map(
worldgeojson, data,
value = "Suicide_Rate",
joinBy = c('name', 'Country_name'),
name = "Suicide Rates"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "Suicide Rate")
hc_corruption <- highchart() %>%
hc_add_series_map(
worldgeojson, data,
value = "Corruption",
joinBy = c('name', 'Country_name'),
name = "Corruption"
) %>%
hc_colorAxis(stops = color_stops()) %>%
hc_title(text = "World Map") %>%
hc_subtitle(text = "Corruption")
# Display the map visualizations
list(hc_life_expectancy, hc_suicide_rates, hc_corruption)
[[1]]
[[2]]
[[3]]
NA
AVG GDP over years
Calculation
avg_gdp_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_gpd = mean(`GDP`))
avg_gdp_per_year
Plot
ggplot(avg_gdp_per_year, aes(x = Year, y = avg_gpd)) +
geom_line(color = "blue") +
labs(title = "Average GDP Over Time worldwide",
x = "Year",
y = "GDP") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_gdp_per_year$Year), max(avg_gdp_per_year$Year), by = 1))

AVG Happiness over years
Calculation
avg_happiness_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_happinnes = mean(`Life_ladder`, na.rm = T))
avg_happiness_per_year
Plot
ggplot(avg_happiness_per_year, aes(x = Year, y = avg_happinnes)) +
geom_line(color = "blue") +
labs(title = "Average Happiness Over Time worldwide",
x = "Year",
y = "Happiness") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_happiness_per_year$Year), max(avg_happiness_per_year$Year), by = 1))

AVG Suicide Rates over years
Calculation
avg_Suicide_Rate_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_Suicide_Rate = mean(`Suicide_Rate`, na.rm = T))
avg_Suicide_Rate_per_year
Plot
ggplot(avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate)) +
geom_line(color = "blue") +
labs(title = "Average Suicide Rate Over Time worldwide",
x = "Year",
y = "Suicide Rate") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_Suicide_Rate_per_year$Year), max(avg_Suicide_Rate_per_year$Year), by = 1))

AVG Bankruptcies over years
Calculation
avg_Bankruptcies_per_year <- data %>%
group_by (`Year`) %>%
summarise(avg_Bankruptcies = mean(`Value`, na.rm = T))
avg_Bankruptcies_per_year
Plot
ggplot(avg_Bankruptcies_per_year, aes(x = Year, y = avg_Bankruptcies)) +
geom_line(color = "blue") +
labs(title = "Average Bankruptcies Over Time worldwide",
x = "Year",
y = "Bankruptcies") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_Bankruptcies_per_year$Year), max(avg_Bankruptcies_per_year$Year), by = 1))

Plot Average GDP and Average Suicide Rate over years
# Finding the ratio for scaling the second axis
ratio <- max(avg_gdp_per_year$avg_gpd) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)
# Creating the base plot
ggplot() +
# Adding the bar plot for GDP
geom_bar(data = avg_gdp_per_year, aes(x = Year, y = avg_gpd), stat = "identity", fill = "skyblue", width = 0.2) +
# Adding the line plot for Average Happiness
geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 1.5) +
# Enhancing the plot
labs(title = "Average GDP and Suicide Rate Over Time",
x = "Year",
y = "Average GDP") +
scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(c(avg_gdp_per_year$Year, avg_Suicide_Rate_per_year$Year)),
max(c(avg_gdp_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

Plot Average Happinness and Average Suicide Rate over years
# Finding the ratio for scaling the second axis
ratio <- max(avg_happiness_per_year$avg_happinnes) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)
# Creating the base plot
ggplot() +
# Adding the bar plot for GDP
geom_bar(data = avg_happiness_per_year, aes(x = Year, y = avg_happinnes), stat = "identity", fill = "skyblue", width = 0.2) +
# Adding the line plot for Average Happiness
geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 1.5) +
# Enhancing the plot
labs(title = "Average Happinness and Suicide Rate Over Time",
x = "Year",
y = "Average Happinness") +
scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)),
max(c(avg_happiness_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Plot Average Bankruptcies and Average Suicide Rate over years
# Finding the ratio for scaling the second axis
ratio <- max(avg_Bankruptcies_per_year$avg_Bankruptcies) / max(avg_Suicide_Rate_per_year$avg_Suicide_Rate)
# Creating the base plot
ggplot() +
# Adding the bar plot for GDP
geom_bar(data = avg_Bankruptcies_per_year, aes(x = Year, y = avg_Bankruptcies), stat = "identity", fill = "skyblue", width = 0.2) +
# Adding the line plot for Average Happiness
geom_line(data = avg_Suicide_Rate_per_year, aes(x = Year, y = avg_Suicide_Rate * ratio), color = "red", size = 1.5) +
# Enhancing the plot
labs(title = "Average Bankruptcies and Suicide Rate Over Time",
x = "Year",
y = "Average Bankruptcies") +
scale_y_continuous(sec.axis = sec_axis(~ . / ratio, name = "Average Suicide Rate")) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(c(avg_Bankruptcies_per_year$Year, avg_Suicide_Rate_per_year$Year)),
max(c(avg_Bankruptcies_per_year$Year, avg_Suicide_Rate_per_year$Year)), by = 1))

Comparisions
Two Happiest and Two unhappiest countries vs average suicide
rate
avg_Suicide_Rate_per_country = data %>%
group_by(Country_name) %>%
summarise(avg_suicide_rate = mean(Suicide_Rate, na.rm = TRUE)) %>%
arrange(avg_suicide_rate) %>%
mutate(Row_Number = row_number())
avg_Suicide_Rate_per_country
avg_happiness_per_country <- data %>%
group_by(Country_name) %>%
summarise(avg_happiness = mean(Life_ladder, na.rm = TRUE)) %>%
arrange(desc(avg_happiness))
least_happy = tail(avg_happiness_per_country, 2)
most_happy = head(avg_happiness_per_country, 2)
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% least_happy$Country_name)
# Interpretation: Japan and South Africa are two very unhappy countries. And they also have a high suicide rate
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% most_happy$Country_name)
# Interpretation: Finland is a the second most happy country. But is still on place 16/19 when it comes to suicides
Two most wealthy countries and two most poor countries vs average
suicide rate
avg_gdp_per_country <- data %>%
group_by (`Country_name`) %>%
summarise(avg_gpd = mean(`GDP`)) %>%
arrange(desc(avg_gpd))
least_gdp = tail(avg_gdp_per_country, 2)
most_gdp = head(avg_gdp_per_country, 2)
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% least_money$Country_name)
Error in `filter()`:
ℹ In argument: `Country_name %in% least_money$Country_name`.
Caused by error:
! object 'least_money' not found
Backtrace:
1. avg_Suicide_Rate_per_country %>% ...
9. Country_name %in% least_money$Country_name
Two most bankcuptcies and two least bankcuptcies countries vs
average suicide rate
avg_Bankruptcies_per_year <- data %>%
group_by (`Country_name`) %>%
summarise(avg_bankruptcies = mean(`Value`, na.rm = T)) %>%
arrange(desc(avg_bankruptcies))
least_bank = tail(avg_Bankruptcies_per_year, 2)
most_bank = head(avg_Bankruptcies_per_year, 2)
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% least_bank$Country_name)
# Interpretation: Bankruptcies don't have an influence on suicide rates
avg_Suicide_Rate_per_country %>%
filter(Country_name %in% most_bank$Country_name)
# Interpretation: Bankruptcies don't have an influence on suicide rates
In depth analysis Germany
Data preperation for Germany
# Prepare data for only Germany
germany_data = data %>%
filter(Country_name == "Germany")
Plot GDP Germany
# Plot Germany GDP over Years
avg_gdp_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_gdp = mean(GDP))
ggplot(avg_gdp_year_germany, aes(x = Year, y = avg_gdp)) +
geom_line(color = "blue") +
labs(title = "Average GPD Over Time - Germany",
x = "Year",
y = "GDP") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_gdp_year_germany$Year), max(avg_gdp_year_germany$Year), by = 1))

Plot Suicide Rate Germany
avg_suicide_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_suicide = mean(Suicide_Rate))
ggplot(avg_suicide_year_germany, aes(x = Year, y = avg_suicide)) +
geom_line(color = "blue") +
labs(title = "Average Suicide Rate Over Time - Germany",
x = "Year",
y = "Suicide Rate") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_suicide_year_germany$Year), max(avg_suicide_year_germany$Year), by = 1))

Plot Bankruptcies Rate Germany
avg_bank_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_bank = mean(Value))
ggplot(avg_bank_year_germany, aes(x = Year, y = avg_bank)) +
geom_line(color = "blue") +
labs(title = "Average bankruptcies Over Time - Germany",
x = "Year",
y = "Bankruptcies") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_bank_year_germany$Year), max(avg_bank_year_germany$Year), by = 1))

Plot Happiness Rate Germany
avg_happiness_year_germany = germany_data %>%
group_by(Year) %>%
summarise(avg_happy = mean(Life_ladder))
ggplot(avg_happiness_year_germany, aes(x = Year, y = avg_happy)) +
geom_line(color = "blue") +
labs(title = "Average Happiness Over Time - Germany",
x = "Year",
y = "Happiness") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_happiness_year_germany$Year), max(avg_happiness_year_germany$Year), by = 1))

In depth analysis South Africa
Data preperation for South Africa
# Prepare data for only Germany
SA_data = data %>%
filter(Country_name == "South Africa")
Plot GDP SA
# Plot Germany GDP over Years
avg_gdp_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_gdp = mean(GDP))
ggplot(avg_gdp_year_SA, aes(x = Year, y = avg_gdp)) +
geom_line(color = "blue") +
labs(title = "Average GPD Over Time - SA",
x = "Year",
y = "GDP") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_gdp_year_SA$Year), max(avg_gdp_year_SA$Year), by = 1))

Plot Suicide Rate SA
avg_suicide_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_suicide = mean(Suicide_Rate))
ggplot(avg_suicide_year_SA, aes(x = Year, y = avg_suicide)) +
geom_line(color = "blue") +
labs(title = "Average Suicide Rate Over Time - SA",
x = "Year",
y = "Suicide Rate") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_suicide_year_SA$Year), max(avg_suicide_year_SA$Year), by = 1))

Plot Happiness Rate SA
avg_happiness_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_happy = mean(Life_ladder))
ggplot(avg_happiness_year_SA, aes(x = Year, y = avg_happy)) +
geom_line(color = "blue") +
labs(title = "Average Happiness Over Time - SA",
x = "Year",
y = "Happiness") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_happiness_year_SA$Year), max(avg_happiness_year_SA$Year), by = 1))

Plot Bankruptcies Rate SA
avg_bank_year_SA = SA_data %>%
group_by(Year) %>%
summarise(avg_bank = mean(Value))
ggplot(avg_bank_year_SA, aes(x = Year, y = avg_bank)) +
geom_line(color = "blue") +
labs(title = "Average bankruptcies Over Time - SA",
x = "Year",
y = "Bankruptcies") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
scale_x_continuous(breaks = seq(min(avg_bank_year_SA$Year), max(avg_bank_year_SA$Year), by = 1))

LS0tCnRpdGxlOiAiUHJlc2VudGF0aW9uIC0gRG9uJ3QgY29tbWl0IFN1aWNpZGUiCmF1dGhvcjogIk1hcmNrZW5yb2xkIENhZGV0ICYgQWxleGFuZGVyIEJ1cmtoYXJ0IgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgIGh0bWxfbm90ZWJvb2s6CiAgICAgICB0b2M6IHRydWUgCiAgICAgICB0b2NfZmxvYXQ6IHRydWUKICAgICAgIHRvY19kZXB0aDogMgogICAgICAgdGhlbWU6IHVuaXRlZAogICAgICAgaGlnaGxpZ2h0OiB0YW5nbwotLS0KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGhpZ2hjaGFydGVyKQpsaWJyYXJ5KG1hZ3JpdHRyKQpgYGAKIyBFREEKIyMgRGF0YSBsb2FkaW5nCmBgYHtyfQpkYXRhIDwtIHJlYWRfY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQWxleGJ1cms5My9EYXRhX1dyYW5nbGluZ19FREEvbWFpbi9kYXRhL3N1aWNpZGVfYW5hbHlzaXMuY3N2IikKICAgICAgICAgICAgICAgIGRhdGEgJT4lIHNhbXBsZV9uKDE5KQpgYGAKIyMgUmVuYW1pbmcgdmFyaWFibGVzIGFuZCBkcm9wIHVud2FudGVkIGNvbHVtbnMKYGBge3J9CiMgcmVuYW1pbmcgdGhlIGNvbHVtbnMgCmRhdGEgPC0gZGF0YSAlPiUKICByZW5hbWUoYENvdW50cnlfbmFtZWAgPSBgQ291bnRyeSBuYW1lYCwKICAgICAgICAgYFN1aWNpZGVfUmF0ZWAgPSBgQWdlLXN0YW5kYXJkaXplZCBzdWljaWRlIHJhdGUgLSBTZXg6IGJvdGggc2V4ZXNgLAogICAgICAgICBgTGlmZV9sYWRkZXJgID0gYExpZmUgTGFkZGVyYCwKICAgICAgICAgYFNvY2lhbF9zdXBwb3J0YCA9IGBTb2NpYWwgc3VwcG9ydGAsCiAgICAgICAgIGBMaWZlX2V4cGVjdGFuY3lgID0gYEhlYWx0aHkgbGlmZSBleHBlY3RhbmN5IGF0IGJpcnRoYCwKICAgICAgICAgYEZyZWVkb21fY2hvaWNlc2AgPSBgRnJlZWRvbSB0byBtYWtlIGxpZmUgY2hvaWNlc2AsCiAgICAgICAgIGBDb3JydXB0aW9uYCA9IGBQZXJjZXB0aW9ucyBvZiBjb3JydXB0aW9uYCwKICAgICAgICAgYEluZGljYXRvcl9uYW1lYCA9IGBJbmRpY2F0b3IgTmFtZWAsCiAgICAgICAgIGBJbmRpY2F0b3JfY29kZWAgPSBgSW5kaWNhdG9yIENvZGVgKQoKIyBkcm9wIGNvbHVtbnMgCiMgcmVtb3ZlIHRoZSBvcmlnaW5hbCAnVGltZScgY29sdW1uCmRhdGEgPC0gc2VsZWN0KGRhdGEsIC1WYXJpYWJsZSwgLUlTSUM0Li4uMTcsIC1JU0lDNC4uLjE4LCAtVkFSLCAtTUVBLCAtYFVuaXQgQ29kZWApICAKZGF0YQpgYGAKIyMgRGF0YSBleHBsb3JhdGlvbgpgYGB7cn0KaGVhZChkYXRhKQpgYGAKCmBgYHtyfQojIGNoYW5nZSBuYW1lcwpuYW1lcyhkYXRhKSA8LSBtYWtlLm5hbWVzKG5hbWVzKGRhdGEpKQpgYGAKCmBgYHtyfQojIGRpbWVuc2lvbnMgb2YgdGhlIGRhdGFmcmFtZQpucm93KGRhdGEpCm5jb2woZGF0YSkKZGltKGRhdGEpCmBgYAoKYGBge3J9CiMgY2hlY2sgdGhlIHN0cnVjdHVyZSBvZiB0aGUgb2JqZWN0CnN0cihkYXRhKQpgYGAKYGBge3J9CiMgbG9vayBhdCBjb2x1bW5zIDYsIDcgYW5kIDEwCmhlYWQoZGF0YVsgLCBjKDIsIDQ6NiwgMTIsIDE1KV0pCmBgYAoKYGBge3J9CiMgbG9vayBhdCBjb2x1bW5zIDYsIDcgYW5kIDEwCnRhaWwoZGF0YVsgLCBjKDEsIDMsIDkpXSkKYGBgCgpgYGB7cn0KdGFibGUoZGF0YSRZZWFyKQpgYGAKCgpgYGB7cn0KZGF0YSAlPiUgCiAgc2VsZWN0KENvdW50cnlfbmFtZSkgJT4lIAogIHVuaXF1ZSgpICU+JSAKICBucm93KCkKYGBgCgpgYGB7cn0KdW5pcXVlKGRhdGEkQ291bnRyeV9uYW1lKQpgYGAKCmBgYHtyfQp1bmlxdWUoZGF0YSRZZWFyKQpgYGAKCiMjIEludGVyYWN0aXZlIG1hcHMKYGBge3J9CiMgU2V0IGhpZ2hjaGFydGVyIG9wdGlvbnMgZm9yIHRvb2x0aXAgZGVjaW1hbHMKb3B0aW9ucyhoaWdoY2hhcnRlci50b29sdGlwLnZhbHVlRGVjaW1hbHMgPSAyKQoKIyBDcmVhdGUgaGlnaGNoYXJ0ZXIgbWFwIHZpc3VhbGl6YXRpb24KaGMgPC0gaGlnaGNoYXJ0KCkgJT4lCiAgaGNfYWRkX3Nlcmllc19tYXAoCiAgICB3b3JsZGdlb2pzb24sIGRhdGEsIHZhbHVlID0gIkdEUCIsIAogICAgam9pbkJ5ID0gYygnbmFtZScsICdDb3VudHJ5X25hbWUnKSwKICAgIG5hbWUgPSAiR0RQIChjdXJyZW50IFVTJCkiCiAgKSAgJT4lIAogIGhjX2NvbG9yQXhpcyhzdG9wcyA9IGNvbG9yX3N0b3BzKCkpICU+JSAKICBoY190aXRsZSh0ZXh0ID0gIldvcmxkIE1hcCIpICU+JSAKICBoY19zdWJ0aXRsZSh0ZXh0ID0gIkdEUCBpbiBjdXJyZW50IFVTJCIpCgpoYwpgYGAKCmBgYHtyfQojIFNldCBoaWdoY2hhcnRlciBvcHRpb25zIGZvciB0b29sdGlwIGRlY2ltYWxzCm9wdGlvbnMoaGlnaGNoYXJ0ZXIudG9vbHRpcC52YWx1ZURlY2ltYWxzID0gMikKCiMgQ3JlYXRlIG1hcCB2aXN1YWxpemF0aW9ucyBmb3IgZWFjaCB2YXJpYWJsZQpoY19saWZlX2V4cGVjdGFuY3kgPC0gaGlnaGNoYXJ0KCkgJT4lCiAgaGNfYWRkX3Nlcmllc19tYXAoCiAgICB3b3JsZGdlb2pzb24sIGRhdGEsIAogICAgdmFsdWUgPSAiTGlmZV9leHBlY3RhbmN5IiwgCiAgICBqb2luQnkgPSBjKCduYW1lJywgJ0NvdW50cnlfbmFtZScpLAogICAgbmFtZSA9ICJMaWZlIEV4cGVjdGFuY3kiCiAgKSAlPiUKICBoY19jb2xvckF4aXMoc3RvcHMgPSBjb2xvcl9zdG9wcygpKSAlPiUKICBoY190aXRsZSh0ZXh0ID0gIldvcmxkIE1hcCIpICU+JQogIGhjX3N1YnRpdGxlKHRleHQgPSAiTGlmZSBFeHBlY3RhbmN5IikKCmhjX3N1aWNpZGVfcmF0ZXMgPC0gaGlnaGNoYXJ0KCkgJT4lCiAgaGNfYWRkX3Nlcmllc19tYXAoCiAgICB3b3JsZGdlb2pzb24sIGRhdGEsIAogICAgdmFsdWUgPSAiU3VpY2lkZV9SYXRlIiwgCiAgICBqb2luQnkgPSBjKCduYW1lJywgJ0NvdW50cnlfbmFtZScpLAogICAgbmFtZSA9ICJTdWljaWRlIFJhdGVzIgogICkgJT4lCiAgaGNfY29sb3JBeGlzKHN0b3BzID0gY29sb3Jfc3RvcHMoKSkgJT4lCiAgaGNfdGl0bGUodGV4dCA9ICJXb3JsZCBNYXAiKSAlPiUKICBoY19zdWJ0aXRsZSh0ZXh0ID0gIlN1aWNpZGUgUmF0ZSIpCgpoY19jb3JydXB0aW9uIDwtIGhpZ2hjaGFydCgpICU+JQogIGhjX2FkZF9zZXJpZXNfbWFwKAogICAgd29ybGRnZW9qc29uLCBkYXRhLCAKICAgIHZhbHVlID0gIkNvcnJ1cHRpb24iLCAKICAgIGpvaW5CeSA9IGMoJ25hbWUnLCAnQ291bnRyeV9uYW1lJyksCiAgICBuYW1lID0gIkNvcnJ1cHRpb24iCiAgKSAlPiUKICBoY19jb2xvckF4aXMoc3RvcHMgPSBjb2xvcl9zdG9wcygpKSAlPiUKICBoY190aXRsZSh0ZXh0ID0gIldvcmxkIE1hcCIpICU+JQogIGhjX3N1YnRpdGxlKHRleHQgPSAiQ29ycnVwdGlvbiIpCgojIERpc3BsYXkgdGhlIG1hcCB2aXN1YWxpemF0aW9ucwpsaXN0KGhjX2xpZmVfZXhwZWN0YW5jeSwgaGNfc3VpY2lkZV9yYXRlcywgaGNfY29ycnVwdGlvbikKCmBgYAoKIyBBVkcgR0RQIG92ZXIgeWVhcnMKIyMgQ2FsY3VsYXRpb24gCmBgYHtyfQphdmdfZ2RwX3Blcl95ZWFyIDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgWWVhcmApICU+JSAKICBzdW1tYXJpc2UoYXZnX2dwZCA9IG1lYW4oYEdEUGApKQoKYXZnX2dkcF9wZXJfeWVhcgpgYGAKIyMgUGxvdCAKYGBge3J9CmdncGxvdChhdmdfZ2RwX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfZ3BkKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEdEUCBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkdEUCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfZ2RwX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX2dkcF9wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCiMgQVZHIEhhcHBpbmVzcyBvdmVyIHllYXJzCiMjIENhbGN1bGF0aW9uIApgYGB7cn0KYXZnX2hhcHBpbmVzc19wZXJfeWVhciA8LSBkYXRhICU+JSAKICBncm91cF9ieSAoYFllYXJgKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19oYXBwaW5uZXMgPSBtZWFuKGBMaWZlX2xhZGRlcmAsIG5hLnJtID0gVCkpCgphdmdfaGFwcGluZXNzX3Blcl95ZWFyCmBgYAojIyBQbG90IAoKYGBge3J9CmdncGxvdChhdmdfaGFwcGluZXNzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfaGFwcGlubmVzKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbmVzcyBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkhhcHBpbmVzcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfaGFwcGluZXNzX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX2hhcHBpbmVzc19wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCgojIEFWRyBTdWljaWRlIFJhdGVzIG92ZXIgeWVhcnMKIyMgQ2FsY3VsYXRpb24gCmBgYHtyfQphdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyIDwtIGRhdGEgJT4lIAogIGdyb3VwX2J5IChgWWVhcmApICU+JSAKICBzdW1tYXJpc2UoYXZnX1N1aWNpZGVfUmF0ZSA9IG1lYW4oYFN1aWNpZGVfUmF0ZWAsIG5hLnJtID0gVCkpCgphdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyCmBgYAojIyBQbG90IAoKYGBge3J9CmdncGxvdChhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfU3VpY2lkZV9SYXRlKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIlN1aWNpZGUgUmF0ZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCiMgQVZHIEJhbmtydXB0Y2llcyBvdmVyIHllYXJzCiMjIENhbGN1bGF0aW9uIApgYGB7cn0KYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciA8LSBkYXRhICU+JSAKICBncm91cF9ieSAoYFllYXJgKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19CYW5rcnVwdGNpZXMgPSBtZWFuKGBWYWx1ZWAsIG5hLnJtID0gVCkpCgphdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyCmBgYAojIyBQbG90IAoKYGBge3J9CmdncGxvdChhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfQmFua3J1cHRjaWVzKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEJhbmtydXB0Y2llcyBPdmVyIFRpbWUgd29ybGR3aWRlIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkJhbmtydXB0Y2llcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyJFllYXIpLCBtYXgoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciRZZWFyKSwgYnkgPSAxKSkKYGBgCgojIFBsb3QgQXZlcmFnZSBHRFAgYW5kIEF2ZXJhZ2UgU3VpY2lkZSBSYXRlIG92ZXIgeWVhcnMKYGBge3J9CiMgRmluZGluZyB0aGUgcmF0aW8gZm9yIHNjYWxpbmcgdGhlIHNlY29uZCBheGlzCnJhdGlvIDwtIG1heChhdmdfZ2RwX3Blcl95ZWFyJGF2Z19ncGQpIC8gbWF4KGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkYXZnX1N1aWNpZGVfUmF0ZSkKCiMgQ3JlYXRpbmcgdGhlIGJhc2UgcGxvdApnZ3Bsb3QoKSArCiAgIyBBZGRpbmcgdGhlIGJhciBwbG90IGZvciBHRFAKICBnZW9tX2JhcihkYXRhID0gYXZnX2dkcF9wZXJfeWVhciwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2dwZCksIHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInNreWJsdWUiLCB3aWR0aCA9IDAuMikgKwogICMgQWRkaW5nIHRoZSBsaW5lIHBsb3QgZm9yIEF2ZXJhZ2UgSGFwcGluZXNzCiAgZ2VvbV9saW5lKGRhdGEgPSBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfU3VpY2lkZV9SYXRlICogcmF0aW8pLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMS41KSArCiAgIyBFbmhhbmNpbmcgdGhlIHBsb3QKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgR0RQIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgR0RQIikgKwogIHNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvIHJhdGlvLCBuYW1lID0gIkF2ZXJhZ2UgU3VpY2lkZSBSYXRlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihjKGF2Z19nZHBfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGMoYXZnX2dkcF9wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgYnkgPSAxKSkKCmBgYAoKIyBQbG90IEF2ZXJhZ2UgSGFwcGlubmVzcyBhbmQgQXZlcmFnZSBTdWljaWRlIFJhdGUgb3ZlciB5ZWFycwpgYGB7cn0KIyBGaW5kaW5nIHRoZSByYXRpbyBmb3Igc2NhbGluZyB0aGUgc2Vjb25kIGF4aXMKcmF0aW8gPC0gbWF4KGF2Z19oYXBwaW5lc3NfcGVyX3llYXIkYXZnX2hhcHBpbm5lcykgLyBtYXgoYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRhdmdfU3VpY2lkZV9SYXRlKQoKIyBDcmVhdGluZyB0aGUgYmFzZSBwbG90CmdncGxvdCgpICsKICAjIEFkZGluZyB0aGUgYmFyIHBsb3QgZm9yIEdEUAogIGdlb21fYmFyKGRhdGEgPSBhdmdfaGFwcGluZXNzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfaGFwcGlubmVzKSwgc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIHdpZHRoID0gMC4yKSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgQXZlcmFnZSBIYXBwaW5lc3MKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19TdWljaWRlX1JhdGUgKiByYXRpbyksIGNvbG9yID0gInJlZCIsIHNpemUgPSAxLjUpICsKICAjIEVuaGFuY2luZyB0aGUgcGxvdAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBIYXBwaW5uZXNzIGFuZCBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkF2ZXJhZ2UgSGFwcGlubmVzcyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoc2VjLmF4aXMgPSBzZWNfYXhpcyh+IC4gLyByYXRpbywgbmFtZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYyhhdmdfaGFwcGluZXNzX3Blcl95ZWFyJFllYXIsIGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhcikpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChjKGF2Z19oYXBwaW5lc3NfcGVyX3llYXIkWWVhciwgYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRZZWFyKSksIGJ5ID0gMSkpCgpgYGAKCiMgUGxvdCBBdmVyYWdlIEJhbmtydXB0Y2llcyBhbmQgQXZlcmFnZSBTdWljaWRlIFJhdGUgb3ZlciB5ZWFycwpgYGB7cn0KIyBGaW5kaW5nIHRoZSByYXRpbyBmb3Igc2NhbGluZyB0aGUgc2Vjb25kIGF4aXMKcmF0aW8gPC0gbWF4KGF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIkYXZnX0JhbmtydXB0Y2llcykgLyBtYXgoYXZnX1N1aWNpZGVfUmF0ZV9wZXJfeWVhciRhdmdfU3VpY2lkZV9SYXRlKQoKIyBDcmVhdGluZyB0aGUgYmFzZSBwbG90CmdncGxvdCgpICsKICAjIEFkZGluZyB0aGUgYmFyIHBsb3QgZm9yIEdEUAogIGdlb21fYmFyKGRhdGEgPSBhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfQmFua3J1cHRjaWVzKSwgc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2t5Ymx1ZSIsIHdpZHRoID0gMC4yKSArCiAgIyBBZGRpbmcgdGhlIGxpbmUgcGxvdCBmb3IgQXZlcmFnZSBIYXBwaW5lc3MKICBnZW9tX2xpbmUoZGF0YSA9IGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19TdWljaWRlX1JhdGUgKiByYXRpbyksIGNvbG9yID0gInJlZCIsIHNpemUgPSAxLjUpICsKICAjIEVuaGFuY2luZyB0aGUgcGxvdAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBCYW5rcnVwdGNpZXMgYW5kIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQXZlcmFnZSBCYW5rcnVwdGNpZXMiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuIC8gcmF0aW8sIG5hbWUgPSAiQXZlcmFnZSBTdWljaWRlIFJhdGUiKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGMoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciRZZWFyLCBhdmdfU3VpY2lkZV9SYXRlX3Blcl95ZWFyJFllYXIpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoYyhhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyJFllYXIsIGF2Z19TdWljaWRlX1JhdGVfcGVyX3llYXIkWWVhcikpLCBieSA9IDEpKQoKYGBgCgojIENvbXBhcmlzaW9ucwoKIyMgVHdvIEhhcHBpZXN0IGFuZCBUd28gdW5oYXBwaWVzdCBjb3VudHJpZXMgdnMgYXZlcmFnZSBzdWljaWRlIHJhdGUKYGBge3J9CmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgPSBkYXRhICU+JQogIGdyb3VwX2J5KENvdW50cnlfbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z19zdWljaWRlX3JhdGUgPSBtZWFuKFN1aWNpZGVfUmF0ZSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShhdmdfc3VpY2lkZV9yYXRlKSAlPiUgCiAgbXV0YXRlKFJvd19OdW1iZXIgPSByb3dfbnVtYmVyKCkpCgphdmdfU3VpY2lkZV9SYXRlX3Blcl9jb3VudHJ5CgphdmdfaGFwcGluZXNzX3Blcl9jb3VudHJ5IDwtIGRhdGEgJT4lCiAgZ3JvdXBfYnkoQ291bnRyeV9uYW1lKSAlPiUKICBzdW1tYXJpc2UoYXZnX2hhcHBpbmVzcyA9IG1lYW4oTGlmZV9sYWRkZXIsIG5hLnJtID0gVFJVRSkpICU+JQogIGFycmFuZ2UoZGVzYyhhdmdfaGFwcGluZXNzKSkKCmxlYXN0X2hhcHB5ID0gIHRhaWwoYXZnX2hhcHBpbmVzc19wZXJfY291bnRyeSwgMikKbW9zdF9oYXBweSA9IGhlYWQoYXZnX2hhcHBpbmVzc19wZXJfY291bnRyeSwgMikKCgphdmdfU3VpY2lkZV9SYXRlX3Blcl9jb3VudHJ5ICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lICVpbiUgbGVhc3RfaGFwcHkkQ291bnRyeV9uYW1lKQoKIyBJbnRlcnByZXRhdGlvbjogSmFwYW4gYW5kIFNvdXRoIEFmcmljYSBhcmUgdHdvIHZlcnkgdW5oYXBweSBjb3VudHJpZXMuIEFuZCB0aGV5IGFsc28gaGF2ZSBhIGhpZ2ggc3VpY2lkZSByYXRlCgphdmdfU3VpY2lkZV9SYXRlX3Blcl9jb3VudHJ5ICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lICVpbiUgbW9zdF9oYXBweSRDb3VudHJ5X25hbWUpCgojIEludGVycHJldGF0aW9uOiBGaW5sYW5kIGlzIGEgdGhlIHNlY29uZCBtb3N0IGhhcHB5IGNvdW50cnkuIEJ1dCBpcyBzdGlsbCBvbiBwbGFjZSAxNi8xOSB3aGVuIGl0IGNvbWVzIHRvIHN1aWNpZGVzCgpgYGAKCiMjIFR3byBtb3N0IHdlYWx0aHkgY291bnRyaWVzIGFuZCB0d28gbW9zdCBwb29yIGNvdW50cmllcyB2cyBhdmVyYWdlIHN1aWNpZGUgcmF0ZQpgYGB7cn0KYXZnX2dkcF9wZXJfY291bnRyeSA8LSBkYXRhICU+JSAKICBncm91cF9ieSAoYENvdW50cnlfbmFtZWApICU+JSAKICBzdW1tYXJpc2UoYXZnX2dwZCA9IG1lYW4oYEdEUGApKSAlPiUgCiAgYXJyYW5nZShkZXNjKGF2Z19ncGQpKQoKbGVhc3RfZ2RwID0gIHRhaWwoYXZnX2dkcF9wZXJfY291bnRyeSwgMikKbW9zdF9nZHAgPSBoZWFkKGF2Z19nZHBfcGVyX2NvdW50cnksIDIpCgphdmdfU3VpY2lkZV9SYXRlX3Blcl9jb3VudHJ5ICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lICVpbiUgbGVhc3RfZ2RwJENvdW50cnlfbmFtZSkKCiMgSW50ZXJwcmV0YXRpb246IE5ldyBaZWFsYW5kIGFuZCBJY2VsYW5kIGFyZSB0d28gdmVyeSBzbWFsbCBjb3VudHJpZXMuICAKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBtb3N0X2dkcCRDb3VudHJ5X25hbWUpCgojIEludGVycHJldGF0aW9uOiBUaGUgdHdvIGJpZ2dlc3QgZWNvbm9taWVzIGFyZSBiYXNlZCBvbiB0aGUgbG93ZXIgZW5kIG9mIHN1aWNpZGUgcmF0ZXMKYGBgCgoKIyMgVHdvIG1vc3QgYmFua2N1cHRjaWVzIGFuZCB0d28gbGVhc3QgYmFua2N1cHRjaWVzIGNvdW50cmllcyB2cyBhdmVyYWdlIHN1aWNpZGUgcmF0ZQpgYGB7cn0KCmF2Z19CYW5rcnVwdGNpZXNfcGVyX3llYXIgPC0gZGF0YSAlPiUgCiAgZ3JvdXBfYnkgKGBDb3VudHJ5X25hbWVgKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19iYW5rcnVwdGNpZXMgPSBtZWFuKGBWYWx1ZWAsIG5hLnJtID0gVCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYXZnX2JhbmtydXB0Y2llcykpCgpsZWFzdF9iYW5rID0gIHRhaWwoYXZnX0JhbmtydXB0Y2llc19wZXJfeWVhciwgMikKbW9zdF9iYW5rID0gaGVhZChhdmdfQmFua3J1cHRjaWVzX3Blcl95ZWFyLCAyKQoKYXZnX1N1aWNpZGVfUmF0ZV9wZXJfY291bnRyeSAlPiUgCiAgZmlsdGVyKENvdW50cnlfbmFtZSAlaW4lIGxlYXN0X2JhbmskQ291bnRyeV9uYW1lKQoKIyBJbnRlcnByZXRhdGlvbjogQmFua3J1cHRjaWVzIGRvbid0IGhhdmUgYW4gaW5mbHVlbmNlIG9uIHN1aWNpZGUgcmF0ZXMKCmF2Z19TdWljaWRlX1JhdGVfcGVyX2NvdW50cnkgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgJWluJSBtb3N0X2JhbmskQ291bnRyeV9uYW1lKQoKIyBJbnRlcnByZXRhdGlvbjogQmFua3J1cHRjaWVzIGRvbid0IGhhdmUgYW4gaW5mbHVlbmNlIG9uIHN1aWNpZGUgcmF0ZXMKYGBgCiMgSW4gZGVwdGggYW5hbHlzaXMgR2VybWFueQojIyBEYXRhIHByZXBlcmF0aW9uIGZvciBHZXJtYW55CmBgYHtyfQojIFByZXBhcmUgZGF0YSBmb3Igb25seSBHZXJtYW55Cmdlcm1hbnlfZGF0YSA9IGRhdGEgJT4lIAogIGZpbHRlcihDb3VudHJ5X25hbWUgPT0gIkdlcm1hbnkiKQpgYGAKCiMjIFBsb3QgR0RQIEdlcm1hbnkKYGBge3J9CiMgUGxvdCBHZXJtYW55IEdEUCBvdmVyIFllYXJzCmF2Z19nZHBfeWVhcl9nZXJtYW55ID0gZ2VybWFueV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19nZHAgPSBtZWFuKEdEUCkpIAoKCmdncGxvdChhdmdfZ2RwX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2dkcCkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBHUEQgT3ZlciBUaW1lIC0gR2VybWFueSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJHRFAiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2dkcF95ZWFyX2dlcm1hbnkkWWVhciksIG1heChhdmdfZ2RwX3llYXJfZ2VybWFueSRZZWFyKSwgYnkgPSAxKSkKCmBgYAoKIyMgUGxvdCBTdWljaWRlIFJhdGUgR2VybWFueQpgYGB7cn0KYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55ID0gZ2VybWFueV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19zdWljaWRlID0gbWVhbihTdWljaWRlX1JhdGUpKSAKCgpnZ3Bsb3QoYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55LCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfc3VpY2lkZSkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBTdWljaWRlIFJhdGUgT3ZlciBUaW1lIC0gR2VybWFueSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJTdWljaWRlIFJhdGUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JFllYXIpLCBtYXgoYXZnX3N1aWNpZGVfeWVhcl9nZXJtYW55JFllYXIpLCBieSA9IDEpKQpgYGAKIyMgUGxvdCBCYW5rcnVwdGNpZXMgUmF0ZSBHZXJtYW55CmBgYHtyfQphdmdfYmFua195ZWFyX2dlcm1hbnkgPSBnZXJtYW55X2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2JhbmsgPSBtZWFuKFZhbHVlKSkgCgoKZ2dwbG90KGF2Z19iYW5rX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2JhbmspKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiKSArICAKICBsYWJzKHRpdGxlID0gIkF2ZXJhZ2UgYmFua3J1cHRjaWVzIE92ZXIgVGltZSAtIEdlcm1hbnkiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQmFua3J1cHRjaWVzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19iYW5rX3llYXJfZ2VybWFueSRZZWFyKSwgbWF4KGF2Z19iYW5rX3llYXJfZ2VybWFueSRZZWFyKSwgYnkgPSAxKSkKYGBgCiMjIFBsb3QgSGFwcGluZXNzIFJhdGUgR2VybWFueQpgYGB7cn0KYXZnX2hhcHBpbmVzc195ZWFyX2dlcm1hbnkgPSBnZXJtYW55X2RhdGEgJT4lIAogIGdyb3VwX2J5KFllYXIpICU+JSAKICBzdW1tYXJpc2UoYXZnX2hhcHB5ID0gbWVhbihMaWZlX2xhZGRlcikpIAoKCmdncGxvdChhdmdfaGFwcGluZXNzX3llYXJfZ2VybWFueSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2hhcHB5KSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbmVzcyBPdmVyIFRpbWUgLSBHZXJtYW55IiwKICAgICAgIHggPSAiWWVhciIsCiAgICAgICB5ID0gIkhhcHBpbmVzcyIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKG1pbihhdmdfaGFwcGluZXNzX3llYXJfZ2VybWFueSRZZWFyKSwgbWF4KGF2Z19oYXBwaW5lc3NfeWVhcl9nZXJtYW55JFllYXIpLCBieSA9IDEpKQpgYGAKIyBJbiBkZXB0aCBhbmFseXNpcyBTb3V0aCBBZnJpY2EKIyMgRGF0YSBwcmVwZXJhdGlvbiBmb3IgU291dGggQWZyaWNhCmBgYHtyfQojIFByZXBhcmUgZGF0YSBmb3Igb25seSBHZXJtYW55ClNBX2RhdGEgPSBkYXRhICU+JSAKICBmaWx0ZXIoQ291bnRyeV9uYW1lID09ICJTb3V0aCBBZnJpY2EiKQpgYGAKCiMjIFBsb3QgR0RQIFNBCmBgYHtyfQojIFBsb3QgR2VybWFueSBHRFAgb3ZlciBZZWFycwphdmdfZ2RwX3llYXJfU0EgPSBTQV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19nZHAgPSBtZWFuKEdEUCkpIAoKCgpnZ3Bsb3QoYXZnX2dkcF95ZWFyX1NBLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfZ2RwKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEdQRCBPdmVyIFRpbWUgLSBTQSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJHRFAiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2dkcF95ZWFyX1NBJFllYXIpLCBtYXgoYXZnX2dkcF95ZWFyX1NBJFllYXIpLCBieSA9IDEpKQoKYGBgCiMjIFBsb3QgU3VpY2lkZSBSYXRlIFNBCmBgYHtyfQphdmdfc3VpY2lkZV95ZWFyX1NBID0gU0FfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfc3VpY2lkZSA9IG1lYW4oU3VpY2lkZV9SYXRlKSkgCgoKZ2dwbG90KGF2Z19zdWljaWRlX3llYXJfU0EsIGFlcyh4ID0gWWVhciwgeSA9IGF2Z19zdWljaWRlKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIFN1aWNpZGUgUmF0ZSBPdmVyIFRpbWUgLSBTQSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJTdWljaWRlIFJhdGUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX3N1aWNpZGVfeWVhcl9TQSRZZWFyKSwgbWF4KGF2Z19zdWljaWRlX3llYXJfU0EkWWVhciksIGJ5ID0gMSkpCmBgYAoKIyMgUGxvdCBIYXBwaW5lc3MgUmF0ZSBTQQpgYGB7cn0KYXZnX2hhcHBpbmVzc195ZWFyX1NBID0gU0FfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoWWVhcikgJT4lIAogIHN1bW1hcmlzZShhdmdfaGFwcHkgPSBtZWFuKExpZmVfbGFkZGVyKSkgCgoKZ2dwbG90KGF2Z19oYXBwaW5lc3NfeWVhcl9TQSwgYWVzKHggPSBZZWFyLCB5ID0gYXZnX2hhcHB5KSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKyAgCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIEhhcHBpbmVzcyBPdmVyIFRpbWUgLSBTQSIsCiAgICAgICB4ID0gIlllYXIiLAogICAgICAgeSA9ICJIYXBwaW5lc3MiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcShtaW4oYXZnX2hhcHBpbmVzc195ZWFyX1NBJFllYXIpLCBtYXgoYXZnX2hhcHBpbmVzc195ZWFyX1NBJFllYXIpLCBieSA9IDEpKQpgYGAKCiMjIFBsb3QgQmFua3J1cHRjaWVzIFJhdGUgU0EKYGBge3J9CmF2Z19iYW5rX3llYXJfU0EgPSBTQV9kYXRhICU+JSAKICBncm91cF9ieShZZWFyKSAlPiUgCiAgc3VtbWFyaXNlKGF2Z19iYW5rID0gbWVhbihWYWx1ZSkpIAoKCmdncGxvdChhdmdfYmFua195ZWFyX1NBLCBhZXMoeCA9IFllYXIsIHkgPSBhdmdfYmFuaykpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmx1ZSIpICsgIAogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBiYW5rcnVwdGNpZXMgT3ZlciBUaW1lIC0gU0EiLAogICAgICAgeCA9ICJZZWFyIiwKICAgICAgIHkgPSAiQmFua3J1cHRjaWVzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEobWluKGF2Z19iYW5rX3llYXJfU0EkWWVhciksIG1heChhdmdfYmFua195ZWFyX1NBJFllYXIpLCBieSA9IDEpKQpgYGA=